/*
 *  w_unit.c
 *  w
 *
 *  Created by Nizar AYED on 05/01/12.
 *  Copyright 2012 FullComMedia. All rights reserved.
 *
 */

#include "w_parser.h"
#include "w_unit.h"

/* Verbose Mode */
bool verbose = false;

/* The test framework */
bool assert_bool(bool expected, bool observed) {
	return (expected == observed);
}
bool assert_int(int expected, int observed){
	return (expected == observed);
}
bool assert_long(long expected, long observed){
	return (expected == observed);
}
bool assert_float(float expected, float observed){
	return (expected == observed);
}
bool assert_string(char* expected, char* observed){
	/* strcmp returns 0 when strings are equal. */
	return (strcmp(expected, observed) ? false : true);
}                                                    
bool assert(int function, char *input, bool result) {
	/* Only first character of the input will be taken into 
	 account if the function requires a char
	 */
	switch (function) {
		case IS_SYMBOL:
			return (is_symbol(input[0])==result);
		case IS_LETTER:
			return (is_letter(input[0])==result);
		case IS_ALPHA:
			return (is_alpha(input[0])==result);
		case IS_DIGIT:
			return (is_digit(input[0])==result);
		case IS_SIGN:
			return (is_sign(input[0])==result);
		case IS_P_CAR:
			return (is_p_car(input[0])==result);
		case IS_ESC_CAR:
			return (is_esc_car(input)==result);
		case IS_SPACE:
			return (is_space(input[0])==result);
		case IS_IDENTIFIER:
			return (is_identifier(input)==result);
		case IS_INT:
			return (is_int(input)==result);
		case IS_FLOAT:
			return (is_float(input)==result);
		case IS_EXPOSANT:
			return (is_exposant(input)==result);
		case IS_STRING:
			return (is_string(input)==result);
		case IS_HEX_CAR:
			return (is_hex_car(input)==result);
		case IS_PROC:
			return (is_proc(input)==result);
		case IS_FUNC:
			return (is_func(input)==result);
		case IS_PARAMS:
			return (is_params(input)==result);
		case IS_CODE:
			return (is_code(input)==result);
		case IS_INSTRUCTION:
			return (is_instruction(input)==result);
		case IS_EQUAL:
			return (is_equal(input)==result);
		case IS_COMMENT_LINE:
			return (is_comment_line(input)==result);
		case IS_COMMENT_MULTILN:
			return (is_comment_multiln(input)==result);
		case IS_HEX_DIGIT:
			return (is_hex_digit(input[0])==result);
		default:
			return false;
	}
}

/* The test suite for w_parser.c */
char* test_id(int test) {
	char* tests[] = { "NO_TEST", //Used for test = 0
		"READ_CHAR", "READ_WORD",
		"IS_SYMBOL", "IS_LETTER", "IS_ALPHA", "IS_DIGIT",
		"IS_SIGN", "IS_P_CAR", "IS_ESC_CAR", "IS_SPACE",
		"IS_IDENTIFIER", "IS_INT", "IS_FLOAT", "IS_EXPOSANT",
		"IS_STRING", "IS_HEX_CAR", "IS_PROC", "IS_FUNC", "IS_PARAMS",
		"IS_CODE", "IS_INSTRUCTION", "IS_EQUAL", "IS_COMMENT_LINE",
		"IS_COMMENT_MULTILN", "IS_HEX_DIGIT" };
	
	return tests[test];
}
int tests[] = { IS_SYMBOL, IS_LETTER, IS_ALPHA, IS_DIGIT,
	IS_SIGN, IS_P_CAR, IS_ESC_CAR, IS_SPACE,
	IS_IDENTIFIER, IS_INT, IS_FLOAT, IS_EXPOSANT,
	IS_HEX_CAR, IS_STRING, IS_PROC, IS_FUNC, IS_PARAMS,
	IS_CODE, IS_INSTRUCTION, IS_EQUAL, IS_COMMENT_LINE,
	IS_COMMENT_MULTILN, IS_HEX_DIGIT,
	0 }; // The last 0 is important
char* inputs[] = {
    // Each line should end by an empty string
    // and last line should be an empty string
    "_", "$", "", // IS_SYMBOL
    "a", "1", "",
    "a", "b", "w", "A", "C", "O", "",  // IS_LETTER
    "8", "-", "‡", "",
    "a", "_", "X", "$", "",  // IS_ALPHA
    "4", "+", "",
    "0", "5", "9", "",  // IS_DIGIT
    "a", "L", "=", "",
    "+", "-", "",  // IS_SIGN
    "i", "(", "#", "",
    "a", "#", "$", "!", "",  // IS_P_CAR
    "\n", "\t", "\x0f", "",
    "\"", "\\", "n", "t", "a", "b", "",  // IS_ESC_CAR
    "l", "m", "o", "z", "w", "",
    " ", "",  // IS_SPACE
    "f", "(", "#", "$", "",
    "_identif", "$var", "var123", "",  // IS_IDENTIFIER
    "12no", "",
	"0", "-13", "+0145", "9456739456554", "++-2", "",  // IS_INT
	"a", "00+4", "132c", "3.1456", "3-1", "",
	"1.2", "4.0", "-3.451e+16", "",  // IS_FLOAT
	"4", "0-1.2", "4.2a4", "",
	"e045", "E+67", "e+-4", "",  // IS_EXPOSANT
	"a1", "exp13", "",
	"\\xfA", "\\X1b", "",  // IS_HEX_CAR
	"\\k12", "\\2e", "",
	"\"abc\"", "\"Af\\tr-\\n\"", "\"a\\x40rbf\"", "",  // IS_STRING
	"\"\\o78\"", "rrft\"", "\"abc", "\"abc\"de", "",
	"?", "",  // IS_PROC
	"?", "",
	"?", "",  // IS_FUNC
	"?", "",
	"x, y, z, ...", "",  // IS_PARAMS
	"1no | l ...", "",
	"?", "",  // IS_CODE
	"?", "",
	"?", "",  // IS_INSTRUCTION
	"?", "",
	"=", "",  // IS_EQUAL
	"k", "",
	"# This is a comment \\n", "",  // IS_COMMENT_LINE
	"// This is not a comment \\t", "",
	"/* Multiligne comment */", "",  // IS_COMMENT_MULTILN
	"Not a comment /* because not ended...", "",
	"a", "E", "C", "5", "",  // IS_HEX_DIGIT
	"G", "-", "",
	""
};
void test_array(){
	int i=0, j=0;
	char *input = inputs[0];
	while(input[0]) {
		while(input[0]) {
			printf("%s: Test %s on %s for TRUE result.\n", 
				   _IS_OK(assert(tests[j], input, true)), test_id(tests[j]), input);
			//printf("Test is %d and Input is %s.\n", tests[j], input);
			input = inputs[++i];
		}
		input = inputs[++i];   
		while(input[0]) {
			printf("%s: Test %s on %s for FALSE result.\n",
				   _IS_OK(assert(tests[j], input, false)), test_id(tests[j]), input); 
			//printf("Test is %d and Input is %s.\n", tests[j], input);
			input = inputs[++i];
		} 
		j++;
		input = inputs[++i];  
	}
}

void test_read_char(char *buffer, char result, bool ok) {
	char c = read_char(buffer);
	char *test = (assert_int(c, result) == ok) ? "OK." : "Not OK.";
	if (verbose) {
		printf("Read char: %c\tExpected: %c\tShould return: %s\n",
			   c,result,_IS_OK(ok));
	}
	printf("Test read_char:%s\n", test);
}

bool test_read_word(FILE *file) {
	rewind(file); /* Important in a test battery */
	char *word = read_word(file);
	printf("1st word is : %s\n", word);
	return assert_string("Hello", word);
}